package humanResource.staffManagement;

import commonInfrastructure.DepartmentSessionBean;
import entity.Staff;
import entity.StaffAccount;
import commonInfrastructure.security.MD5;
import java.util.ArrayList;

import java.util.List;
import java.util.UUID;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import commonInfrastructure.communication.EmailManager;
import javax.ejb.EJB;

@Stateless
public class StaffAccountManagementSession implements StaffAccountManagementSessionRemote {

    @PersistenceContext
    private EntityManager entityManager;
    @EJB
    DepartmentSessionBean departmentSessionBean;
    
    @Override
    public Staff getStaffById(Long id){
        return entityManager.find(Staff.class, id);
    }

    //Search Staff
    @Override
    public List<Staff> searchStaff(Long staffID, String firstName, String lastName) {
        String strQuery = "SELECT s from Staff s WHERE";
        String and = " and";

        boolean hasParameter = false;

        if (staffID != null) {
            strQuery = strQuery + " s.staffID = :inStaffID";
            hasParameter = true;
        } else if (firstName != null) {
            if (hasParameter) {
                strQuery = strQuery + and;
            }
            strQuery = strQuery + " s.firstName = :inFirstName";
            hasParameter = true;
        } else if (lastName != null) {
            if (hasParameter) {
                strQuery = strQuery + and;
            }
            strQuery = strQuery + " s.lastName = :inLastName";
            hasParameter = true;
        }

        System.out.println(strQuery);

        if (!hasParameter) {
            return null;
        }

        Query query = entityManager.createQuery(strQuery);

        if (staffID != null) {
            Long ID = Long.valueOf(staffID);
            query.setParameter("inStaffID", ID);
        } else if (firstName != null) {
            query.setParameter("inFirstname", firstName);
        } else if (lastName != null) {
            query.setParameter("inLastname", lastName);
        }

        return query.getResultList();
    }

    @Override
    public Character checkDomain(String username) {
        Character domain;
        Query query = entityManager.createQuery("SELECT s FROM StaffAccount s WHERE s.staffAccountName = :inStaffAccountName");
        query.setParameter("inStaffAccountName", username);

        StaffAccount staffAccount = (StaffAccount) query.getResultList().get(0);
        domain = staffAccount.getStaffDomain();
        return domain;
    }

    @Override
    public Staff searchOneStaff(String user) {

        Query query = entityManager.createQuery("SELECT s FROM StaffAccount s WHERE s.staffAccountName = :inStaffAccountName");
        query.setParameter("inStaffAccountName", user);

        StaffAccount staffAccount = (StaffAccount) query.getResultList().get(0);
        Staff staff = staffAccount.getStaff();

        return staff;
    }

    //return 0 is empty field
    //return long int staff ID is created successfully
    @Override
    public long addStaff(String firstName, String lastName, String email, String officeExtension, String personalContact, String departmentName) {
        if (firstName == null || lastName == null || email == null || personalContact == null || departmentName == null) {
            return 0;
        }

        Staff staff = new Staff();
        staff.setFirstName(firstName);
        staff.setLastName(lastName);
        staff.setEmail(email);
        staff.setOfficeExtension(officeExtension);
        staff.setPersonalContact(personalContact);
        entityManager.persist(staff);
        entityManager.flush();
        return staff.getStaffID();
    }

    @Override
    public long addStaffAccount(Long staffID, String staffAccountName) {
        StaffAccount sa = new StaffAccount();
        Staff staff = entityManager.find(Staff.class, staffID);
        staffAccountName = staffAccountName.toLowerCase();
        sa.setStaffAccountName(staffAccountName);
        sa.setStaff(staff);
        sa.setTries(0);
        String password0 = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 7);
        String password = MD5.MD5(password0);
        sa.setPassword(password);
        sa.setActive(true);

        entityManager.persist(sa);
        entityManager.flush();
        
        EmailManager emailManager = new EmailManager(staff.getEmail(), "New staff account created for you", "Account Name: " + staffAccountName + "\nInitial password: " + password0);  
        Thread thread = new Thread(emailManager);
        thread.start();

        return sa.getStaffAccountID();
    }

    //List all staff in the system
    @Override
    public List<Staff> listAllStaff() {
        String strQuery = "SELECT s from Staff s ";
        Query query = entityManager.createQuery(strQuery);
        List<Staff> resultList = query.getResultList();
        List<Staff> result = new ArrayList();
        for (Staff s : resultList) {
            if (s.getStaffAccount() == null) {
                continue;
            }
            if (s.getStaffAccount().isActive()) {
                result.add(s);
            }
        }
        return resultList;
    }

    @Override
    public List<StaffAccount> listAllStaffAccount() {
        String strQuery = "SELECT s from StaffAccount s ";
        Query qurey = entityManager.createQuery(strQuery);
        return qurey.getResultList();
    }

    @Override
    public void updatePersonalInfo(String userAccountName, String email, String firstName, String lastName, String officeExtension, String personalContact) {
        Query query = entityManager.createQuery("SELECT s FROM StaffAccount s WHERE s.staffAccountName = :inStaffAccountName");
        query.setParameter("inStaffAccountName", userAccountName);

        StaffAccount staffAccount = (StaffAccount) query.getResultList().get(0);
        Staff staff = staffAccount.getStaff();

        staff.setFirstName(firstName);
        staff.setLastName(lastName);
        staff.setEmail(email);
        staff.setOfficeExtension(officeExtension);
        staff.setPersonalContact(personalContact);

        entityManager.merge(staff);
        entityManager.flush();
    }

    @Override
    public void updateStaff(Long staffID, String email, String firstName, String lastName, String officeExtension, String personalContact) {

        Staff staff = entityManager.find(Staff.class, staffID);
        staff.setFirstName(firstName);
        staff.setLastName(lastName);
        staff.setEmail(email);
        staff.setOfficeExtension(officeExtension);
        staff.setPersonalContact(personalContact);

        entityManager.merge(staff);
        entityManager.flush();
    }

    @Override
    public void updateStaff2(String user, String email, String firstName, String lastName, String officeExtension, String personalContact) {


        Query query = entityManager.createQuery("SELECT s FROM StaffAccount s WHERE s.staffAccountName = :inStaffAccountName");
        query.setParameter("inStaffAccountName", user);

        StaffAccount staffAccount = (StaffAccount) query.getResultList().get(0);
        Staff staff = staffAccount.getStaff();

        staff.setFirstName(firstName);
        staff.setLastName(lastName);
        staff.setEmail(email);
        staff.setOfficeExtension(officeExtension);
        staff.setPersonalContact(personalContact);

        entityManager.merge(staff);
        entityManager.flush();
    }

    @Override
    public boolean checkStaffExist(String firstName, String lastName) {
        String strQuery = "SELECT s FROM Staff s WHERE s.firstName = :infirstName AND s.lastName = :inlastName";
        Query query = entityManager.createQuery(strQuery);
        query.setParameter("infirstName", firstName);
        query.setParameter("inlastName", lastName);

        int size = query.getResultList().size();
        if (size > 0) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public boolean checkStaffAccountExist(String staffAccountName) {
        if (staffAccountName == null) {
            return false;
        }

        String strQuery = "SELECT s FROM StaffAccount s WHERE s.staffAccountName = :instaffAccountName";
        Query query = entityManager.createQuery(strQuery);
        query.setParameter("instaffAccountName", staffAccountName);

        int size = query.getResultList().size();
        if (size > 0) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void activeStaffAccount(Long StaffAccountID) {
        StaffAccount sa = entityManager.find(StaffAccount.class, StaffAccountID);
        sa.setActive(true);
        entityManager.persist(sa);
        entityManager.flush();
    }

    @Override
    public void deactiveStaffAccount(Long StaffAccountID) {
        StaffAccount sa = entityManager.find(StaffAccount.class, StaffAccountID);
        if (sa == null) {
            return;
        }
        sa.setActive(false);
        entityManager.persist(sa);
        entityManager.flush();
    }

    @Override
    public String resetPassword(String StaffAccountID, String email) {
        String strQuery = "SELECT s FROM StaffAccount s WHERE s.staffAccountName = :instaffAccountName";
        Query query = entityManager.createQuery(strQuery);
        query.setParameter("instaffAccountName", StaffAccountID);

        StaffAccount sa = (StaffAccount) query.getResultList().get(0);
        System.out.println("MARK");
        if (!sa.getStaff().getEmail().equals(email)) {
            return "Staff ID and email does not match!";
        }

        String new_password = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 7);
        System.out.println(new_password);

        String password = MD5.MD5(new_password);
        System.out.println("MD5: " + password);
        sa.setPassword(password);
        sa.setActive(true);
        sa.setTries(0);
        entityManager.persist(sa);
        entityManager.flush();

        EmailManager emailManager = new EmailManager(sa.getStaff().getEmail(), "Password changed for you", "Your new password has been changed to: " + new_password);
        Thread thread = new Thread(emailManager);
        thread.start();

        return "New password has been created and emailed to you.";
    }

    @Override
    public void changePassword(Long StaffAccountID, String new_password) {
        StaffAccount sa = entityManager.find(StaffAccount.class, StaffAccountID);
        new_password = MD5.MD5(new_password);
        sa.setPassword(new_password);

        entityManager.persist(sa);
        entityManager.flush();
    }

    @Override
    public StaffAccount getStaffAccount(String staffAccountName) {
        Query query = entityManager.createQuery("SELECT s FROM StaffAccount s WHERE s.staffAccountName = :staffAccountName");
        query.setParameter("staffAccountName", staffAccountName);
        return (StaffAccount) query.getResultList().get(0);
    }

    @Override
    public void setContacts(Long StaffAccountID, List<String> contacts) {
        StaffAccount sa = entityManager.find(StaffAccount.class, StaffAccountID);
        sa.setContacts(contacts);
        entityManager.persist(sa);
        entityManager.flush();
    }

    @Override
    public Long getStaffAccountIDfromStaffAccountName(String staffAccountName) {
        Query query = entityManager.createQuery("SELECT s FROM StaffAccount s WHERE s.staffAccountName = :staffAccountName");
        query.setParameter("staffAccountName", staffAccountName);
        return ((StaffAccount) query.getResultList().get(0)).getStaffAccountID();
    }
    
    @Override
    public void deleteStaff(Long id){
        Staff s = entityManager.find(Staff.class, id);
        entityManager.remove(s);
        entityManager.flush();
    }
    
    @Override
    public void deleteStaffAccount(Long id){
        StaffAccount s = entityManager.find(StaffAccount.class, id);
        entityManager.remove(s);
        entityManager.flush();
    }
}